﻿using CsvHelper;
using HalconDotNet;
using LeaderCCSLaserUI.Data;
using LeaderCCSLaserUI.Data.Extensions;
using LeaderCCSLaserUI.Models;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using NLog;
using Prism.Commands;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Xml.Linq;
using MessageBox = System.Windows.Forms.MessageBox;

namespace LeaderCCSLaserUI.ViewModels.Dialogs
{
    public class ZControlDialogViewModel : DialogViewModel
    {
        #region 变量
        private static Logger logger = LogManager.GetCurrentClassLogger();
        private Param? systemParam;
        private bool isModified = false;
        #endregion
        #region 属性
        private bool isDoubleAlBarControl;
        public bool IsDoubleAlBarControl
        {
            get { return isDoubleAlBarControl; }
            set { SetProperty(ref isDoubleAlBarControl, value); }
        }
        private bool isZControlStudy;
        public bool IsZControlStudy
        {
            get { return isZControlStudy; }
            set { SetProperty(ref isZControlStudy, value); }
        }
        private double zDistUpLimit;
        public double ZDistUpLimit
        {
            get { return zDistUpLimit; }
            set { SetProperty(ref zDistUpLimit, value); }
        }
        private double zDistLowLimit;
        public double ZDistLowLimit
        {
            get { return zDistLowLimit; }
            set { SetProperty(ref zDistLowLimit, value); }
        }
        private ObservableCollection<string> barcodeList = new ObservableCollection<string>();
        public ObservableCollection<string> BarcodeList
        {
            get { return barcodeList; }
            set { SetProperty(ref barcodeList, value); }
        }
        private ObservableCollection<ZControlPointDisp> pointList1 = new ObservableCollection<ZControlPointDisp>();
        public ObservableCollection<ZControlPointDisp> PointList1
        {
            get { return pointList1; }
            set { SetProperty(ref pointList1, value); }
        }
        private ObservableCollection<ZControlPointDisp> pointList2 = new ObservableCollection<ZControlPointDisp>();
        public ObservableCollection<ZControlPointDisp> PointList2
        {
            get { return pointList2; }
            set { SetProperty(ref pointList2, value); }
        }
        #endregion
        #region 函数
        private DelegateCommand<object> doubleAlBarControlSwitchCommand;
        public DelegateCommand<object> DoubleAlBarControlSwitchCommand =>
    doubleAlBarControlSwitchCommand ?? (doubleAlBarControlSwitchCommand = new DelegateCommand<object>(ExecuteDoubleAlBarControlSwitchCommand));
        private DelegateCommand<object> zControlStudyCommand;
        public DelegateCommand<object> ZControlStudyCommand =>
            zControlStudyCommand ?? (zControlStudyCommand = new DelegateCommand<object>(ExecuteZControlStudyCommand));
        private DelegateCommand<object> barcodeListSelectCommand;
        public DelegateCommand<object> BarcodeListSelectCommand =>
            barcodeListSelectCommand ?? (barcodeListSelectCommand = new DelegateCommand<object>(ExecuteBarcodeListSelectCommand));
        private DelegateCommand<object> textBoxLostFocusCommand;
        public DelegateCommand<object> TextBoxLostFocusCommand =>
            textBoxLostFocusCommand ?? (textBoxLostFocusCommand = new DelegateCommand<object>(ExecuteTextBoxLostFocusCommand));
        private DelegateCommand<object> pointList1RowEditEndingCommand;
        public DelegateCommand<object> PointList1RowEditEndingCommand =>
            pointList1RowEditEndingCommand ?? (pointList1RowEditEndingCommand = new DelegateCommand<object>(ExecutePointList1RowEditEndingCommand));
        private DelegateCommand<object> deleteCommand;
        public DelegateCommand<object> DeleteCommand =>
            deleteCommand ?? (deleteCommand = new DelegateCommand<object>(ExecuteDeleteCommand));
        private DelegateCommand<object> exporteCommand;
        public DelegateCommand<object> ExporteCommand =>
            exporteCommand ?? (exporteCommand = new DelegateCommand<object>(ExecuteExporteCommand));

        void ExecuteExporteCommand(object obj)
        {
            if (obj != null)
            {
                if (obj is string barcode)
                {
                    try
                    {
                        SaveFileDialog saveFileDialog1 = new SaveFileDialog();
                        saveFileDialog1.InitialDirectory = @"C:\";
                        saveFileDialog1.Title = "Save csv Files";
                        saveFileDialog1.CheckFileExists = false;
                        saveFileDialog1.CheckPathExists = true;
                        saveFileDialog1.DefaultExt = "csv";
                        saveFileDialog1.Filter = "csv files (*.csv)|*.csv|All files (*.*)|*.*";
                        saveFileDialog1.FilterIndex = 1;
                        saveFileDialog1.RestoreDirectory = true;
                        if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        {
                            using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                            var zbars = mdb.ZControlPoints.Where(z => z.Barcode == barcode).OrderBy(z => z.Hand).ThenBy(z => z.PcsOrder);
                            if (zbars.Any())
                            {
                                using (var writer = new StreamWriter(saveFileDialog1.FileName))
                                using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                                {
                                    csv.WriteRecords(zbars);
                                }
                            }
                            MessageBox.Show("导出完成", "错误", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                  
                }
               
            }
            else
            {
                MessageBox.Show("未选择任何载具", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        void ExecuteDeleteCommand(object obj)
        {
            if (obj != null)
            {
                if (obj is string barcode)
                {
                    try
                    {
                        if (MessageBox.Show($"确认要清除\"{barcode}\"吗？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)
                        {
                            using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                            mdb.Database.ExecuteSqlRaw($"DELETE FROM ZControlPoints WHERE Barcode = '{barcode}'");
                            mdb.SaveChanges();
                            LoadData();
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
            else
            {
                MessageBox.Show("未选择任何载具", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        void ExecutePointList1RowEditEndingCommand(object obj)
        {
            if (obj is ZControlPointDisp zdisp)
            {
                using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                var zp = mdb.ZControlPoints.FirstOrDefault(z => z.Id == zdisp.Id);
                if (zp != null)
                {
                    zp.ZPos = zdisp.ZPos;
                    zp.Dist = zdisp.Dist;
                    zp.UpLimit = zdisp.UpLimit;
                    zp.LowLimit = zdisp.LowLimit;
                    mdb.SaveChanges();
                }
            }
        }
        void ExecuteTextBoxLostFocusCommand(object obj)
        {
            if (obj is string str)
            {
                switch (str)
                {
                    case "ZDistUpLimit":
                        {
                            using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                            var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "ZDistUpLimit");
                            if (_mParam != null)
                            {
                                _mParam.Value = ZDistUpLimit.ToString();
                                mdb.SaveChanges();
                            }
                        }
                        break;
                    case "ZDistLowLimit":
                        {
                            using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                            var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "ZDistLowLimit");
                            if (_mParam != null)
                            {
                                _mParam.Value = ZDistLowLimit.ToString();
                                mdb.SaveChanges();
                            }
                        }
                        break;
                    default:
                        break;
                }
                isModified = true;
            }
        }
        void ExecuteBarcodeListSelectCommand(object obj)
        {
            if (obj is string barcode)
            {
                PointList1.Clear();
                PointList2.Clear();
                using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                var zbars = mdb.ZControlPoints.Where(z => z.Hand == 0 && z.Barcode == barcode).OrderBy(z => z.PcsOrder);
                if (zbars.Any())
                {
                    zbars.ToList().ForEach(z => {
                        PointList1.Add(new ZControlPointDisp { 
                            Id = z.Id,
                            Barcode = z.Barcode,
                            PcsOrder = z.PcsOrder,
                            Name = z.Name,
                            ZPos = z.ZPos,
                            Dist = z.Dist,
                            UpLimit = z.UpLimit,
                            LowLimit = z.LowLimit
                        });
                    });
                }
                zbars = mdb.ZControlPoints.Where(z => z.Hand == 1 && z.Barcode == barcode).OrderBy(z => z.PcsOrder);
                if (zbars.Any())
                {
                    zbars.ToList().ForEach(z => {
                        PointList2.Add(new ZControlPointDisp
                        {
                            Id = z.Id,
                            Barcode = z.Barcode,
                            PcsOrder = z.PcsOrder,
                            Name = z.Name,
                            ZPos = z.ZPos,
                            Dist = z.Dist,
                            UpLimit = z.UpLimit,
                            LowLimit = z.LowLimit
                        });
                    });
                }
            }
        }
        void ExecuteZControlStudyCommand(object obj)
        {
            if (obj is bool v1)
            {
                using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "IsZControlStudy");
                if (_mParam != null)
                {
                    _mParam.Value = v1.ToString();
                    mdb.SaveChanges();
                }
            }
        }
        void ExecuteDoubleAlBarControlSwitchCommand(object obj)
        {
            if (obj is bool v1)
            {
                using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
                var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "IsDoubleAlBarControl");
                if (_mParam != null)
                {
                    _mParam.Value = v1.ToString();
                    mdb.SaveChanges();
                }
            }
        }
        #endregion
        #region 导航
        public override void OnDialogClosed()
        {
            if (isModified)
            {
                aggregator.SendMessage("ReloadParam", "Run");
            }
        }
        public override void OnDialogOpened(IDialogParameters parameters)
        {
            LoadParam();
            using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
            var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "IsDoubleAlBarControl");
            if (_mParam != null)
            {
                if (bool.TryParse(_mParam.Value, out var _v))
                {
                    IsDoubleAlBarControl = _v;
                }
                else
                {
                    IsDoubleAlBarControl = false;
                    _mParam.Value = IsDoubleAlBarControl.ToString();
                    mdb.SaveChanges();
                }
            }
            else
            {
                IsDoubleAlBarControl = false;
                mdb.MParams.Add(new MParam
                {
                    Name = "IsDoubleAlBarControl",
                    Value = IsDoubleAlBarControl.ToString(),
                    Type = typeof(bool).Name,
                    Hand = 0
                });
                mdb.SaveChanges();
            }
            _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "IsZControlStudy");
            if (_mParam != null)
            {
                if (bool.TryParse(_mParam.Value, out var _v))
                {
                    IsZControlStudy = _v;
                }
                else
                {
                    IsZControlStudy = false;
                    _mParam.Value = IsZControlStudy.ToString();
                    mdb.SaveChanges();
                }
            }
            else
            {
                IsZControlStudy = false;
                mdb.MParams.Add(new MParam
                {
                    Name = "IsZControlStudy",
                    Value = IsZControlStudy.ToString(),
                    Type = typeof(bool).Name,
                    Hand = 0
                });
                mdb.SaveChanges();
            }
            _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "ZDistUpLimit");
            if (_mParam != null)
            {
                if (double.TryParse(_mParam.Value, out var _v))
                {
                    ZDistUpLimit = _v;
                }
                else
                {
                    ZDistUpLimit = 1.5;
                    _mParam.Value = ZDistUpLimit.ToString();
                    mdb.SaveChanges();
                }
            }
            else
            {
                ZDistUpLimit = 1.5;
                mdb.MParams.Add(new MParam
                {
                    Name = "ZDistUpLimit",
                    Value = ZDistUpLimit.ToString(),
                    Type = typeof(double).Name,
                    Hand = 0
                });
                mdb.SaveChanges();
            }
            _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "ZDistLowLimit");
            if (_mParam != null)
            {
                if (double.TryParse(_mParam.Value, out var _v))
                {
                    ZDistLowLimit = _v;
                }
                else
                {
                    ZDistLowLimit = -1.5;
                    _mParam.Value = ZDistLowLimit.ToString();
                    mdb.SaveChanges();
                }
            }
            else
            {
                ZDistLowLimit = -1.5;
                mdb.MParams.Add(new MParam
                {
                    Name = "ZDistLowLimit",
                    Value = ZDistLowLimit.ToString(),
                    Type = typeof(double).Name,
                    Hand = 0
                });
                mdb.SaveChanges();
            }

            LoadData();
        }
        #endregion
        #region 构造函数
        public ZControlDialogViewModel(IContainerProvider containerProvider) : base(containerProvider)
        {
            Title = "双铝巴管控";
        }
        #endregion
        #region 功能函数
        void LoadParam()
        {
            try
            {
                //Json序列化，从文件读取
                string jsonString = File.ReadAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Param.json"));
                systemParam = JsonConvert.DeserializeObject<Param>(jsonString);
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
        }
        private void LoadData()
        {
            BarcodeList.Clear();
            PointList1.Clear();
            PointList2.Clear();
            using var mdb = new MDbContext(systemParam.PartList[systemParam.PartIndex]);
            var zpoints = mdb.ZControlPoints.Where(z => z.Id > 0);
            if (zpoints.Any())
            {
                zpoints.ToList().ForEach(z => {
                    if (!BarcodeList.Contains(z.Barcode))
                    {
                        BarcodeList.Add(z.Barcode.Substring(0));
                    }
                });
            }
        }
        #endregion
    }
}
